#ifndef RACE_H
#define RACE_H

#include <iostream>
#include <vector>

#include "lib.h"
#include "Prerequis.h"
#include "ListCapa.h"
#include "StatusCode.h"

#include <boost/assign/list_of.hpp>

using namespace std;

/**
 * La classe Race représente une race au sens AD&D. C'est une classe
 * abstraite, qui sert au polymorphisme.
 *
 * La classe permet de gérer les diverses capacités raciales et
 * éventuels ensembles raciaux, qui sont lus depuis les types de
 * races. L'objet Race possède les méthodes et attributs communs à
 * toutes les races.
 *
 * @author Johan "Solo" Luisier
 */
class Race
{
 protected:
  /**
   * Capacités raciales. On stocke uniquement le numéro de la capacité
   * dans ce conteneur.
   */
  vector<unsigned int> capacites;
  /**
   * Niveau de sortie des méthodes de base, c'est à dire très
   * simple. On peut changer la valeur de cette constante en modifiant
   * la ligne Race::élémentaire du fichier CONFIG
   *
   * @see DebugLevelType
   * @see debugstream 
   */
  static DebugLevelType elementaire;
  /**
   * Niveau de sortie des fonctions plus élaborées. La valeur de cette
   * constante est définie par la ligne Race::fonction du fichier
   * CONFIG
   *
   * @see DebugLevelType
   * @see debugstream 
   */
  static DebugLevelType fonction;
  /**
   * Nom de la Race (Elfe, Gnome, Humain, ...)
   */
  string Type;
  /**
   * Pointeur sur la liste des capacités raciales, permet d'avoir
   * accès aux capacités (noms, cout en pp) de la race considérée.
   */
  const vector< ListCapa > *ptrCapa;
  /**
   * Pointeur sur les ensembles raciaux, qui permet d'accéder aux
   * éventuels ensembles raciaux. Ce pointeur est nul s'il n'existe
   * pas d'ensembles raciaux.
   */
  const vector< vector< unsigned int > > *ptrEns;
  /**
   * Pointeur sur le nombre de capcités raciales de la Race, relique
   * du temps où les capacités étaient stockées dans un tableau
   * statique.
   */
  const unsigned int *ptrNbrCapa;
  /**
   * Pointeur sur le nombre d'ensembles raciaux, datant également du
   * temps où les ensembles raciaux étaient des tableaux statiques.
   * Est égal au nombre de lignes de la "matrice" pointée par ptrEns.
   */
  const unsigned int *ptrNbrEns;
  /**
   * Pointeur sur le nombre max de capacités dans un ensemble racial,
   * donne la longueur maximale des lignes de la matrice pointée pas
   * ptrEns.
   */
  const unsigned int *ptrMaxEns;
  /**
   * Pointeur sur la liste des ensembles raciaux. Si la Race n'a pas
   * de tels ensembles, ce pointeur est nul.
   */
  const vector< ListCapa > *ptrNomEns;
  /**
   * Pointeur sur le conteneur des prérequis raciaux. Cela permet
   * d'éviter de créer un Demi-Ogre avec 20 de Charisme par exemple.
   */
  const vector< Prerequis > *ptrPreRequis;
 public:
  Race(const string& type);
  Race(const Race& race);
  virtual ~Race();
  virtual void appliquerAjustements(unsigned int tab[7]);
  void afficheInfo(ostream& os = blank()) const;
  string getType() const;
  unsigned int getTaille() const;
  unsigned int getCapa(const unsigned int& i) const;
  string getCapacite(const unsigned int& i) const;
  const vector< unsigned int >* getCapacitesAdresse() const;
  void getCapacites(unsigned int& nbr, vector<ListCapa>& capa) const;
  const vector< ListCapa >* getCapacites() const;
  void getDonneesEnsRaciaux(unsigned int& nbr, unsigned int& max) const;
  const vector< ListCapa >* getNomsEnsemblesRaciaux() const;
  const vector<unsigned int>* getEnsembleRacial(const unsigned int& nbr) const;
  unsigned int getPP() const;
  void setCapacites(const vector<unsigned int>& capa);
  static void setLevel(const DebugLevelType& level, const unsigned int& n);
  const vector<unsigned int>* getToutesCapacites(unsigned int& nbr) const;
  void construitRace(unsigned int& pps);
  StatusCode rempliPrerequis(unsigned int tab[7]);
};


#endif
